package com.guang.executor.executorpool;

import com.guang.interupt.ThreadInteruptOne;
import com.sun.javafx.runtime.SystemProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lg
 * @Description
 * @date 2022/10/24 17:39
 */
public class ExecutorPoolTestOne {
    private static Logger logger = LoggerFactory.getLogger(ExecutorPoolTestOne.class);
    private static int CORE_THREAD_COUNT = Runtime.getRuntime().availableProcessors()+1;
    private static final String FIX_THREAD_NAME = "FixThreadPool_";

    // 不需要临时线程了，因为LinkedBlockingDeque默认长度是2^31-1
    // TODO 惰性加载 当最开始的时候是放入到线程池中的时候，才会创建一个新的线程。而不是说在创建的时候直接创建新线程
    private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(CORE_THREAD_COUNT,
            CORE_THREAD_COUNT,
            5, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(),
            // 给线程起一个名字，方便后面在排查问题的时候知道是哪里的线程执行什么任务造成的
            new ThreadFactory() {
                    AtomicInteger atomicInteger = new AtomicInteger(1);
                    // 自定义生产线程的工厂
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r,FIX_THREAD_NAME+atomicInteger.getAndIncrement());
                }
                // 如果队列满了，又来了新的任务，无法执行新来的任务的时候将会直接拒绝掉当前任务！
                // 可以看到里面传递的参数：当前任务+线程池  最常见的无非就是等待为空的时候再次放入到线程池中来进行执行
            },new ThreadPoolExecutor.AbortPolicy()
    );

    public static void main(String[] args) throws InterruptedException {
        logger.info("让主线程开始来执行任务，但是太占用主线程时间，直接开启线程池来执行任务");
        for (int i = 0; i < 10; i++) {
            EXECUTOR_SERVICE.execute(new MyTask());
        }
        // 其实主线程应该在这里等待线程中的任务执行完成的
        // 那么如何知道线程池中的任务执行完成了呢？

    }

    private static class MyTask implements Runnable{
        @Override
        public void run() {
            logger.info("在执行线程任务的时候打印当前线程名称:{}",Thread.currentThread().getName());
            logger.info("start..........");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("end..........");
        }
    }


}
